use crate::gen_title;

// 变量可变性
pub fn ch2_1_1() {
    gen_title("ch2_1_1", 18);
    // 必须有mut 否则不可改变变量的值
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

/// ### 使用下划线开头忽略未使用的变量
pub fn ch2_1_2() {
    gen_title("ch2_1_2", 18);
    // 下划线开头可忽略不使用变量的警告
    let _x = 5;
    let y = 10;
    println!("The value of y is: {}", y);
}

/// ### 变量解构
pub fn ch2_1_3() {
    gen_title("ch2_1_3", 18);
    let (a, mut b): (bool, bool) = (true, false);
    // a=true不可变, b=false可变
    println!("a = {:?}, b = {:?}", a, b);

    b = true;
    assert_eq!(a, b);
}

/// ### 解构式赋值
pub fn ch2_1_4() {
    gen_title("ch2_1_4", 18);
    struct Struct {
        e: i32,
    }

    let (a, b, c, d, e);

    (a, b) = (1, 2);
    // _代表匹配一个值, 但并不关心具体的值是什么,因此没有使用一个变量名而是使用了下划线
    [c, .., d, _] = [1, 2, 3, 4, 5];
    Struct { e, .. } = Struct { e: 5 };

    assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
    println!(
        "a = {:?}, b = {:?}, c = {:?}, d = {:?}, e = {:?}",
        a, b, c, d, e
    );
}

/// ### 变量遮蔽
/// 第二个 `let` 生成了完全不同的新变量, 涉及内存对象的再分配,
/// 而 `mut` 声明的变量可以修改同一个内存地址上的值, 不会发生内存对象再分配, 性能更好
pub fn ch2_1_5() {
    gen_title("ch2_1_5", 18);
    let x = 5;
    // 在 main 函数的作用于内对之前的 x 进行屏蔽
    let x = x + 1;

    {
        // 在当前花括号的作用域内, 对之前的 x 进行屏蔽
        let x = x + 2;
        println!("The value of x in the inner scope is: {}", x);
    }

    println!("The value of x is: {}", x);
}

/// ### 练习一: 绑定与可变性
pub fn ch2_1_pra_1() {
    gen_title("ch2_1_pra_1", 18);
    let x: i32 = 3;
    let _y: i32;
    println!("x is equal to {}", x);
}

pub fn ch2_1_pra_2() {
    gen_title("ch2_1_pra_2", 18);
    let mut x = 1;
    x += 2;

    println!("x = {}", x);
}

/// ### 练习二: 变量作用域
pub fn ch2_1_pra_3() {
    gen_title("ch2_1_pra_3", 18);
    let x: i32 = 10;
    {
        let y: i32 = 5;
        println!("x 的值是 {}, y 的值是 {}", x, y);
    }
    println!("x 的值是 {}", x);
}

pub fn ch2_1_pra_4() {
    gen_title("ch2_1_pra_4", 18);
    fn define_x() -> Box<str> {
        Box::from("hello")
    }

    println!("{}, world", define_x());
}

/// ### 变量遮蔽
pub fn ch2_1_pra_5() {
    gen_title("ch2_1_pra_5", 18);

    let x: i32 = 5;
    {
        let x = 12;
        assert_eq!(x, 12);
    }

    assert_eq!(x, 5);

    let x = 42;
    println!("{}", x);
}

pub fn ch2_1_pra_6() {
    gen_title("ch2_1_pra_6", 18);
    let mut x: i32 = 1;
    x = 7;
    let mut x = x;
    x += 3;

    let _y = 4;
    let y = "I can also be bound to text";

    println!("x = {}, y = {}", x, y);
}

/// ### 变量解构
pub fn ch2_1_pra_7() {
    gen_title("ch2_1_pra_7", 18);

    let (mut x, y) = (1, 2);
    x += 2;

    println!("x = {}, y = {}", x, y);
}

/// ### 解构式赋值
pub fn ch2_1_pra_8() {
    gen_title("ch2_1_pra_8", 18);

    let (x, y);
    (x, ..) = (3, 4);
    [.., y] = [1, 2];
    assert_eq!([x, y], [3, 2]);
    println!("[x, y] = {:?}", [x, y]);
}
